﻿using SvnAPI.Base.Enumerator;
using SvnAPI.Command.Interface;
using System;
using System.Configuration;
using System.Diagnostics;

namespace SvnAPI.Command.Base
{
    /// <summary>
    /// Base class to execute the specific command on svn tools and execute the process 
    /// to call the executable of thata command and wait for the result. 
    /// </summary>
    public abstract class BaseCommand : IDisposable
    {
        #region Variables

        /// <summary>
        /// Environment variable to get the path to start the execution.
        /// </summary>
        protected String SVN_SERVER = String.Empty;

        #endregion

        #region Properties

        /// <summary>
        /// File Name of svn tool to execute the command.
        /// </summary>
        protected String FileName { get; set; }

        /// <summary>
        /// Arguments to execute the command.
        /// </summary>
        protected String Arguments { get; set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor for the class.
        /// </summary>
        protected BaseCommand()
        {
            String ConfigSvnServer = ConfigurationManager.AppSettings["SVN_SERVER"];

            if (ConfigSvnServer != null)
            {
                SVN_SERVER = Environment.GetEnvironmentVariable(ConfigSvnServer);

                if (SVN_SERVER == null || SVN_SERVER == String.Empty)
                {
                    SVN_SERVER = Environment.GetEnvironmentVariable("VISUALSVN_SERVER");

                    // Just now.
                    if (SVN_SERVER == null || SVN_SERVER == String.Empty)
                    {
                        SVN_SERVER = @"C:\Program Files\TortoiseSVN\";
                    }
                }
            }
        }

        #endregion

        #region Methods    

        /// <summary>
        /// Mehod to execute the command with parameters requireds and get the result on Error and Output.
        /// </summary>
        protected virtual IResult Run()
        {
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName = this.FileName,
                    Arguments = this.Arguments,
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true
                };

                using (Process process = new Process() { StartInfo = startInfo })
                {
                    process.Start();
                    process.WaitForExit();

                    String error = process.StandardError.ReadToEnd().Trim();
                    String output = process.StandardOutput.ReadToEnd().Trim();

                    return new Result()
                    {
                        Error = error,
                        Output = output,
                        ResultType = error != String.Empty ? ResultType.error : ResultType.output
                    };
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
        
        /// <summary>
        /// Abstract method to dispose the command executed.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispose the object and resources.
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Free Resources.
            }
        }

        #endregion
    }    
}